home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / role / pinfocom_3_0.lha / Source / print.c < prev    next >
C/C++ Source or Header  |  1992-10-22  |  10KB  |  467 lines

  1. /* print.c
  2.  *
  3.  *  ``pinfocom'' -- a portable Infocom Inc. data file interpreter.
  4.  *  Copyright (C) 1987-1992  InfoTaskForce
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; see the file COPYING.  If not, write to the
  18.  *  Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /*
  22.  * $Header: RCS/print.c,v 3.0 1992/10/21 16:56:19 pds Stab $
  23.  */
  24.  
  25. #include <stdio.h>
  26. #include <string.h>
  27.  
  28. #include "infocom.h"
  29.  
  30. #define BUFMIN              80
  31. #define LONG_SCORE_WIDTH    60
  32. #define MAX_MOVES           1599
  33. #define STATLEN             24
  34.  
  35. int     print_mode;     /* General Printing Mode           */
  36. int     single_mode;    /* Mode for printing the next char */
  37.  
  38. static word word_bank;  /* There are 3 banks of common     */
  39.                         /* words, each 32 words long.      */
  40.  
  41. static print_buf_t text, room;
  42.  
  43. static char score_buf[STATLEN+1];
  44.  
  45. void
  46. print_init()
  47. {
  48.     extern print_buf_t  *pbf_p;
  49.     extern char         *ti_location;
  50.     extern char         *ti_status;
  51.  
  52.     text.len = 0;
  53.     text.max = BUFMIN * 5;
  54.     text.buf = (byte *)xmalloc(text.max + 1);
  55.     pbf_p = &text;
  56.  
  57.     room.max = BUFMIN;
  58.     room.buf = (byte *)xmalloc(room.max + 1);
  59.     room.buf[0] = ' ';
  60.     room.len = 1;
  61.  
  62.     ti_location = (char *)room.buf;
  63.     ti_status = (char *)score_buf;
  64. }
  65.  
  66. void
  67. print_num A1(word, number)
  68. {
  69.     Bool    neg;
  70.     int     num;
  71.     char    buf[15], *cp;
  72.  
  73.     num = (signed_word)number;
  74.     if (neg = (num < 0))
  75.         num = -num;
  76.  
  77.     cp = buf;
  78.     do
  79.     {
  80.         *(cp++) = '0' + (num % 10);
  81.         num /= 10;
  82.     }
  83.     while (num > 0);
  84.  
  85.     if (neg)
  86.         *cp = '-';
  87.     else
  88.         --cp;
  89.  
  90.     for (; cp >= buf; --cp)
  91.         print_char((word)*cp);
  92. }
  93.  
  94. /*
  95.  * Print a hex number in a fixed-width space -- NOTE: this function
  96.  * cannot be called with a value > 0xff if !is_eobj, or 0xffff if
  97.  * is_eobj.
  98.  */
  99. char *
  100. print_hnum A1(word, num)
  101. {
  102.     static char buf[10];
  103.     char *cp;
  104.  
  105.     cp = &buf[(objd.is_eobj+1) * 2];
  106.     cp[1] = '\0';
  107.     do
  108.     {
  109.         int i;
  110.  
  111.         i = num % 16;
  112.         *(cp--) = i > 9 ? 'a'+(i-10) : '0'+i;
  113.         num /= 16;
  114.     }
  115.     while (num > 0);
  116.  
  117.     while (cp > buf)
  118.         *(cp--) = '0';
  119.     *cp = '$';
  120.  
  121.     return (buf);
  122. }
  123.  
  124. void
  125. print_str A1(const char *, str)
  126. {
  127.     while (*str != '\0')
  128.         print_char((word)*str++);
  129. }
  130.  
  131. void
  132. print2 A1(word, address)
  133. {
  134.     word    page;
  135.     word    offset;
  136.  
  137.     page = address >> 8;
  138.     offset = (address & 0xFF) << 1;
  139.     prt_coded(&page, &offset);
  140. }
  141.  
  142. void
  143. print1 A1(word, address)
  144. {
  145.     word    page;
  146.     word    offset;
  147.  
  148.     page = address / BLOCK_SIZE;
  149.     offset = address % BLOCK_SIZE;
  150.     prt_coded(&page, &offset);
  151. }
  152.  
  153. void
  154. p_obj A1(word, obj_num)
  155. {
  156.     object_t    *obj;
  157.     word        address;
  158.     word        page;
  159.     word        offset;
  160.  
  161.     obj = obj_addr(obj_num);
  162.     address = Z_TO_WORD(obj->data);
  163.     page = address / BLOCK_SIZE;
  164.     offset = address % BLOCK_SIZE;
  165.  
  166.     /*
  167.      * The first byte at the address is the length of the data: if
  168.      * it's 0 then there's nothing to print, so don't.
  169.      */
  170.     if (get_byte(&page, &offset) > 0)
  171.     {
  172.         prt_coded(&page, &offset);
  173.     }
  174. }
  175.  
  176. void
  177. wrt()
  178. {
  179.     extern word     pc_page;
  180.     extern word     pc_offset;
  181.  
  182.     prt_coded(&pc_page, &pc_offset);
  183.     fix_pc();
  184. }
  185.  
  186. void
  187. writeln()
  188. {
  189.     wrt();
  190.     new_line();
  191.     rtn(1);
  192. }
  193.  
  194. void
  195. new_line()
  196. {
  197.     extern print_buf_t  *pbf_p;
  198.  
  199.     pbf_p->buf[pbf_p->len] = '\0';
  200.     scr_putline((char *)pbf_p->buf);
  201.     pbf_p->len = 0;
  202. }
  203.  
  204. const char *
  205. chop_buf A2(const char *, buf, int, max)
  206. {
  207.     const char *ptr;
  208.     int len;
  209.  
  210.     /*
  211.      * Find the current length; if it's <= max already then we're done.
  212.      */
  213.     if ((len = strlen(buf)) <= max)
  214.         return (&buf[len]);
  215.  
  216.     /*
  217.      * Find the last space at or before buf[max]
  218.      */
  219.     for (ptr = &buf[max]; (*ptr != ' ') && (ptr > buf); --ptr)
  220.     {}
  221.  
  222.     /*
  223.      * If the word takes up the whole line then search forward for the
  224.      * next space (it won't fit, but if they're asking for such a small
  225.      * width as to give 1 word per line, whaddaya gonna do?)
  226.      */
  227.     if (ptr == buf)
  228.         for (ptr = &buf[max+1]; (*ptr != ' ') && (*ptr != '\0'); ++ptr)
  229.         {}
  230.  
  231.     return (ptr);
  232. }
  233.  
  234. void
  235. print_char A1(word, ch)
  236. {
  237.     extern print_buf_t *pbf_p;
  238.  
  239.     /*
  240.      * If we're at the end of the buffer then get some more memory...
  241.      */
  242.     if (pbf_p->len == pbf_p->max)
  243.     {
  244.         pbf_p->max += BUFMIN;
  245.         pbf_p->buf = (byte *)xrealloc(pbf_p->buf, pbf_p->max + 1);
  246.     }
  247.  
  248.     pbf_p->buf[pbf_p->len++] = (byte)ch;
  249. }
  250.  
  251. void
  252. prt_coded A2(word*, page, word*, offset)
  253. {
  254.     word    data;
  255.  
  256.     /*
  257.      * Print mode = < 0 :   Common Word;
  258.      *              = 0 :   Lower Case Letter;
  259.      *              = 1 :   Upper Case Letter;
  260.      *              = 2 :   Number or Symbol;
  261.      *              = 3 :   ASCII Letter - first byte;
  262.      *              > 3 :   ASCII Letter - second byte;
  263.      */
  264.     print_mode = 0;
  265.     single_mode = 0;
  266.  
  267.     /* Last word has high bit set */
  268.     do
  269.     {
  270.         data = get_word(page, offset);
  271.         decode(data);
  272.     }
  273.     while ((data & 0x8000) == 0);
  274. }
  275.  
  276. static void
  277. letter A1(char, ch)
  278. {
  279.     extern char     table[];
  280.  
  281.     if (ch == 0)
  282.     {
  283.         print_char((word)' ');
  284.         single_mode = print_mode;
  285.         return;
  286.     }
  287.  
  288.     if (ch <= 3)
  289.     {
  290.         /* Set single_mode to "Common Word" & set word_bank */
  291.  
  292.         single_mode |= 0x80;
  293.         word_bank = (ch - 1) << 6;
  294.         return;
  295.     }
  296.  
  297.     if ((ch == 4) || (ch == 5))
  298.     {
  299.         /* Switch printing modes */
  300.  
  301.         if (single_mode == 0)
  302.             single_mode = ch - 3;
  303.         else
  304.         {
  305.             if (single_mode == ch - 3)
  306.                 single_mode = 0;
  307.             print_mode = single_mode;
  308.         }
  309.         return;
  310.     }
  311.  
  312.     if ((ch == 6) && (single_mode == 2))
  313.     {
  314.         /* Increment printing mode to 3 - ASCII Letter. */
  315.  
  316.         ++single_mode;
  317.         return;
  318.     }
  319.  
  320.     if ((ch == 7) && (single_mode == 2))
  321.     {
  322.         /* Print a Carriage Return */
  323.  
  324.         new_line();
  325.         single_mode = print_mode;
  326.         return;
  327.     }
  328.  
  329.     /* None of the above, so this must be a single character */
  330.  
  331.     print_char((word)table[(single_mode * 26) + ch - 6]);
  332.     single_mode = print_mode;
  333. }
  334.  
  335. void
  336. decode A1(word, data)
  337. {
  338.     extern byte     *common_word_ptr;
  339.  
  340.     word            page;
  341.     word            offset;
  342.     word            code;
  343.     int             i;
  344.     byte            *ptr;
  345.     char            ch[3];
  346.  
  347.     /* Reduce word to 3 characters of 5 bits */
  348.  
  349.     code = data;
  350.     for (i = 0; i <= 2; i++)
  351.     {
  352.         ch[i] = code & 0x1F;
  353.         code >>= 5;
  354.     }
  355.  
  356.     /* Print each character */
  357.  
  358.     for (i = 2; i >= 0; i--)
  359.     {
  360.         if (single_mode & 0x80)
  361.         {
  362.             /* Print a Special Word */
  363.  
  364.             ptr = common_word_ptr + word_bank + (int)(ch[i] << 1);
  365.             page = Z_TO_BYTE_I(ptr);
  366.             offset = Z_TO_BYTE(ptr) << 1;
  367.             prt_coded(&page, &offset);
  368.             single_mode = print_mode;
  369.             continue;
  370.         }
  371.         if (single_mode < 3)
  372.         {
  373.             /* Print a single character */
  374.  
  375.             letter(ch[i]);
  376.             continue;
  377.         }
  378.         if (single_mode == 3)
  379.         {
  380.             /*
  381.              * Print ASCII character - store the high 3 bits of
  382.              * char in the low 3 bits of the current printing mode.
  383.              */
  384.  
  385.             single_mode = 0x40 + ch[i];
  386.             continue;
  387.         }
  388.         if (single_mode & 0x40)
  389.         {
  390.             /*
  391.              * Print an ASCII character - consists of the current
  392.              * character as the low 5 bits and the high 3 bits coming
  393.              * from the low 3 bits of the current printing mode.
  394.              */
  395.  
  396.             ch[i] += (single_mode & 0x03) << 5;
  397.             print_char((word)ch[i]);
  398.             single_mode = print_mode;
  399.         }
  400.     }
  401. }
  402.  
  403. void
  404. set_score()
  405. {
  406.     static const char *mv_str=NULL, *mv_alt=NULL;
  407.     extern print_buf_t  *pbf_p;
  408.  
  409.     /*
  410.      * Set the description
  411.      */
  412.     pbf_p = &room;
  413.     room.len = 1;
  414.     p_obj(load_var(0x10));
  415.     room.buf[room.len] = '\0';
  416.     pbf_p = &text;
  417.  
  418.     /*
  419.      * Fill in the score or time fields...
  420.      */
  421.     if (F1_IS_SET(B_USE_TIME))
  422.     {
  423.         word    hour;
  424.         char    ch;
  425.  
  426.         hour = load_var(0x11);
  427.  
  428.         /* Convert 24 hour time to AM/PM */
  429.  
  430.         ch = 'A';
  431.         if (hour >= 12)
  432.         {
  433.             hour -= 12;
  434.             ch = 'P';
  435.         }
  436.         if (hour == 0)
  437.             hour = 12;
  438.  
  439.         sprintf(score_buf, "Time: %2hu:%02hu %cM ", hour, load_var(0x12), ch);
  440.     }
  441.     else
  442.     {
  443.         short int moves;
  444.  
  445.         moves = (short int)load_var(0x12);
  446.  
  447.         if (mv_str == NULL)
  448.             if (moves > MAX_MOVES)
  449.             {
  450.                 mv_str = "GST";
  451.                 mv_alt = "T";
  452.             }
  453.             else
  454.             {
  455.                 mv_str = "Moves";
  456.                 mv_alt = "M";
  457.             }
  458.  
  459.         if ((text.max < 0) || (text.max > LONG_SCORE_WIDTH))
  460.             sprintf(score_buf, "Score: %-3hd  %s: %-4hd ",
  461.                     (short int)load_var(0x11), mv_str, moves);
  462.         else
  463.             sprintf(score_buf, "S: %-3hd  %s: %-4hd ",
  464.                     (short int)load_var(0x11), mv_alt, moves);
  465.     }
  466. }
  467.